﻿
Public Class cHandShake
    Implements IDisposable


    Public blowfish As New BlowfishNET.BlowfishECB
    Dim dwArgs(17) As UInt32


    Function Packet_0x5000_len9(ByVal packet() As Byte) As Byte()
        Dim key As Int64
        Dim keybyte As Byte
        Dim keyArray(7) As Byte


        ' ######################################################
        ' #### -------------- Check Handshake -------------- ###
        ' ######################################################

        key = dwArgs(5)
        key = key << 32
        key += dwArgs(4)
        keyArray = BitConverter.GetBytes(key)

        keybyte = LoBYTE(LoWord(dwArgs(4))) And &H7
        Func_X_2(keyArray, dwArgs(14), keybyte)




        blowfish.EncryptRev(keyArray, 0, keyArray, 0, 8)

        Dim handshakecheck As UInt64
        Using r As New IO.BinaryReader(New IO.MemoryStream(packet))
            r.BaseStream.Position += 7 'header +1
            handshakecheck = r.ReadUInt64
        End Using

        If BitConverter.ToUInt64(keyArray, 0) <> handshakecheck Then
            Return Nothing
        End If



        ' ######################################################
        ' ### ------------- Generate Final Key ------------- ###
        ' ######################################################
        key = dwArgs(16)
        key = key << 32
        key += dwArgs(15)
        keyArray = BitConverter.GetBytes(key)

        Func_X_2(keyArray, dwArgs(6), &H3)

        Return keyArray 'final key 

    End Function
    Public Structure sRetVal
        Dim packet() As Byte
        Dim SeedCounter As UInt32
        Dim SeedCrc As UInt32
    End Structure
    Function Packet_0x5000_len37(ByVal packet() As Byte) As sRetVal
        Dim flag As Byte
        Dim bfkey(7) As Byte
        Dim seedcounter As UInt32
        Dim seedCRC As UInt32
        Dim seedSecurity(4) As UInt32

        Using r As New IO.BinaryReader(New IO.MemoryStream(packet))
            r.BaseStream.Position += 6 'header
            flag = r.ReadByte
            r.ReadUInt64()
            seedcounter = r.ReadUInt32
            seedCRC = r.ReadUInt32
            seedSecurity(0) = r.ReadUInt32
            seedSecurity(1) = r.ReadUInt32
            seedSecurity(2) = r.ReadUInt32
            seedSecurity(3) = r.ReadUInt32
            seedSecurity(4) = r.ReadUInt32
        End Using




        'Store the seeds into the arguments
        dwArgs(10) = seedSecurity(3)
        dwArgs(11) = seedSecurity(2)
        dwArgs(12) = seedSecurity(4)
        dwArgs(15) = seedSecurity(0)
        dwArgs(16) = seedSecurity(1)


        dwArgs(0) = dwArgs(11)
        dwArgs(1) = dwArgs(10)
        dwArgs(3) = CUInt(Int((&H7FFFFFFF * Rnd()) + &H10))
        dwArgs(5) = Func_X_4(dwArgs(1), dwArgs(3), dwArgs(0))


        dwArgs(13) = dwArgs(5)
        dwArgs(4) = dwArgs(12)
        dwArgs(6) = Func_X_4(dwArgs(1), dwArgs(3), dwArgs(4))
        dwArgs(14) = dwArgs(6)

        '-------------------------------------------
        Dim keyByte As Byte
        Dim keyArray As UInt64 = 0
        Dim keyArray1(7) As Byte
        Dim keyArray2(7) As Byte
        ' Generate the private blowfish key
        keyByte = LoBYTE(dwArgs(14)) And &H3

        keyArray = dwArgs(13)
        keyArray = keyArray << 32
        keyArray += dwArgs(12)
        keyArray1 = BitConverter.GetBytes(keyArray)

        Func_X_2(keyArray1, dwArgs(14), keyByte)


        keyArray = dwArgs(4)
        keyArray = keyArray << 32
        keyArray += dwArgs(5)
        keyArray2 = BitConverter.GetBytes(keyArray)
        keyByte = LoBYTE(LoWord(dwArgs(5))) And &H7
        Func_X_2(keyArray2, dwArgs(14), keyByte)

        blowfish.Initialize(keyArray1, 0, 8)

        blowfish.EncryptRev(keyArray2, 0, keyArray2, 0, 8)

        'Dim antwort As New cPacket(&H5000, False, packet.Dest)
        'antwort.data.Add_UInt32(dwArgs(13))
        'antwort.data.add_byte(keyArray2)




        Dim aPacket(17) As Byte 'fucking vb.net 0 base  base stuff
        Using w As New IO.BinaryWriter(New IO.MemoryStream(aPacket))
            w.Write(CShort(w.BaseStream.Length - 6)) 'len
            w.Write(CShort(&H5000)) 'opc
            w.Write(CShort(0)) ' sec
            w.Write(dwArgs(13))
            w.Write(keyArray2)
            w.Flush()
        End Using

        Packet_0x5000_len37.SeedCrc = seedCRC
        Packet_0x5000_len37.SeedCounter = seedcounter
        Packet_0x5000_len37.packet = aPacket

    End Function


#Region "helper functions"
    Public Function LoWord(ByVal int As Int32) As Int64
        Return int And &HFFFF
    End Function
    Public Function HiWord(ByVal int As Int32) As Int64
        Return (int And &HFFFF0000) >> 16
    End Function
    Function LoBYTE(ByVal int As Int32) As Int64
        Return int And &HFF
    End Function
    Function HiBYTE(ByVal int As Int32) As Int64
        Return (int And &HFF00) >> 8
    End Function

    Sub Func_X_2(ByRef stream() As Byte, ByVal key As Int32, ByVal keybyte As Byte)
        stream(0) = LoBYTE(stream(0) Xor (stream(0) + LoBYTE(LoWord(key)) + keybyte))
        stream(1) = LoBYTE(stream(1) Xor (stream(1) + HiBYTE(LoWord(key)) + keybyte))
        stream(2) = LoBYTE(stream(2) Xor (stream(2) + LoBYTE(HiWord(key)) + keybyte))
        stream(3) = LoBYTE(stream(3) Xor (stream(3) + HiBYTE(HiWord(key)) + keybyte))
        stream(4) = LoBYTE(stream(4) Xor (stream(4) + LoBYTE(LoWord(key)) + keybyte))
        stream(5) = LoBYTE(stream(5) Xor (stream(5) + HiBYTE(LoWord(key)) + keybyte))
        stream(6) = LoBYTE(stream(6) Xor (stream(6) + LoBYTE(HiWord(key)) + keybyte))
        stream(7) = LoBYTE(stream(7) Xor (stream(7) + HiBYTE(HiWord(key)) + keybyte))
    End Sub
    Function Func_X_4(ByVal P As UInt32, ByVal X As UInt32, ByVal G As UInt32)

        Dim result As Int64 = 1
        Dim mult As Int64 = G
        If X = 0 Then Return 1
        While X
            '(mult * result) - (p * ((mult * result) \ p)) 
            If (X And 1) Then result = (mult * result) Mod P
            X = X >> 1
            mult = (mult * mult) Mod P
        End While
        Return CUInt(result)

    End Function
#End Region

    Private disposedValue As Boolean = False        ' So ermitteln Sie überflüssige Aufrufe

    ' IDisposable
    Protected Overridable Sub Dispose(ByVal disposing As Boolean)
        If Not Me.disposedValue Then
            If disposing Then
                ' TODO: Anderen Zustand freigeben (verwaltete Objekte).
                blowfish = Nothing
                dwArgs = Nothing
            End If

            ' TODO: Eigenen Zustand freigeben (nicht verwaltete Objekte).
            ' TODO: Große Felder auf NULL festlegen.
        End If
        Me.disposedValue = True
    End Sub

#Region " IDisposable Support "
    ' Dieser Code wird von Visual Basic hinzugefügt, um das Dispose-Muster richtig zu implementieren.
    Public Sub Dispose() Implements IDisposable.Dispose
        ' Ändern Sie diesen Code nicht. Fügen Sie oben in Dispose(ByVal disposing As Boolean) Bereinigungscode ein.
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub
#End Region

End Class